package MP.syntaxanalysis;
import MP.lexicalanalysis.*;

public abstract class AST {
	public AST parent;
	abstract void visit(Visitor a);
}
class ProgramAST extends AST{
	VarDeclPartAST 	v;
	ProDeclPartAST 	p;
	CompStatAST	c;
	ProgramAST(VarDeclPartAST var, ProDeclPartAST pro, CompStatAST com) {
		v = var;
		p = pro;
		c = com;
		v.parent = p.parent =  c.parent = this;		
	}
	
	 void visit(Visitor v) {
		v.visitProgramAST(this);		
  }
	
}


class VarDeclPartAST extends AST {
	OneDeclAST 	o;
	VarDeclPartAST	v;
	VarDeclPartAST() {
		o = null;
		v = null;
	}
	VarDeclPartAST(OneDeclAST one, VarDeclPartAST var) {
		v = var;
		o = one;
		v.parent = o.parent = this;
	}
	
	void visit(Visitor v) {
		v.visitVarDeclPartAST(this);
	}
}
class EmptyVarDeclPartAST extends VarDeclPartAST {

	EmptyVarDeclPartAST() {
			
	}

	void visit(Visitor v) {
		v.visitEmptyVarDeclPartAST(this);
	}
}

abstract class OneDeclAST extends AST {
	Token name;
}
class VarDeclAST extends OneDeclAST {
	TypeAST		t;
	VarDeclAST(Token n, TypeAST type) {
		name = n;
		t = type;
		t.parent = this;
	}
	
	void visit(Visitor v) {
		v.visitVarDeclAST(this);
	}
}

class ConstDeclAST extends OneDeclAST {
	LiteralAST	l;
	ConstDeclAST(Token n, LiteralAST lit) {
		name = n;
		l = lit;
		l.parent = this;
	}
	
	void visit(Visitor v) {
		v.visitConstDeclAST(this);
	}
}

abstract class TypeAST extends AST{	
}
abstract class PrimTypeAST extends TypeAST {
}

class IntTypeAST extends PrimTypeAST{
	void visit(Visitor v) {
		v.visitIntTypeAST(this);
	}
}

class RealTypeAST extends PrimTypeAST{
	void visit(Visitor v) {
		v.visitRealTypeAST(this);
}
}
class BoolTypeAST extends PrimTypeAST{
	void visit(Visitor v) {
		v.visitBoolTypeAST(this);
}
}
class ArrayTypeAST extends TypeAST {
	PrimTypeAST	type;
	Token		lower;
	Token		upper;
	ArrayTypeAST(PrimTypeAST prim,Token n1, Token n2 ){
		type=prim;
		lower=n1;
		upper=n2;
		type.parent=this;		
	}
	void visit(Visitor v){
		v.visitArrayTypeAST(this);
	}
}
abstract class LiteralAST extends ExprAST {
	Token 		literal;

}
class IntLiteralAST extends LiteralAST {
	IntLiteralAST (Token t) {
		literal = t;
	}
	
	void visit(Visitor v) {
		v.visitIntLiteralAST(this);
	}
}
class RealLiteralAST extends LiteralAST {
	RealLiteralAST (Token t) {
		literal = t;
	}
	
	void visit(Visitor v) {
		v.visitRealLiteralAST(this);
	}
}
class BoolLiteralAST extends LiteralAST {
	BoolLiteralAST (Token t) {
		literal = t;
	}
	
	void visit(Visitor v) {
		v.visitBoolLiteralAST(this);
	}
}
class StringLiteralAST extends LiteralAST {
	StringLiteralAST (Token t) {
		literal = t;
	}
	
	void visit(Visitor v) {
		v.visitStringLiteralAST(this);
	}
}
class ProDeclPartAST extends AST{
	OneProcDeclAST 	o;
	ProDeclPartAST	p;
	ProDeclPartAST() {
		o = null;
		p = null;
	}
	ProDeclPartAST(OneProcDeclAST one, ProDeclPartAST pro){
		o = one;
		p = pro;
		o.parent = p.parent = this;		
	}
	void visit(Visitor v){
		v.visitProDeclPartAST(this);
	}
}
class EmptyProDeclPartAST extends ProDeclPartAST {
	EmptyProDeclPartAST() {
		super();		
	}
	void visit(Visitor v) {
		v.visitEmptyProDeclPartAST(this);
	}
}
abstract class OneProcDeclAST extends AST{
	Token		name;
	ParaListAST	para;
	VarDeclPartAST	v;
	ProDeclPartAST	p;
	CompStatAST	c;
}

class ProcDeclAST extends OneProcDeclAST {
	ProcDeclAST(Token n,ParaListAST pl, VarDeclPartAST vdecl, ProDeclPartAST pro, CompStatAST comp) {
		name = n;
		para = pl;
		v  = vdecl;
		p = pro;
		c = comp;
		para.parent = v.parent = p.parent = c.parent = this;
	}
	void visit(Visitor v) {
		v.visitProcDeclAST(this);
	}
}
class FuncDeclAST extends OneProcDeclAST {
	TypeAST		ret;
	FuncDeclAST(Token n,ParaListAST pl, TypeAST rt, VarDeclPartAST vdecl, ProDeclPartAST pro, CompStatAST comp) {
		name = n;
		para = pl;
		ret = rt;
		v  = vdecl;
		p = pro;
		c = comp;
		para.parent = v.parent = ret.parent = p.parent = c.parent = this;
	}


	void visit(Visitor v) {
		v.visitFuncDeclAST(this);
	}
}	
class ParaListAST extends AST{
	VarDeclAST	v;
	ParaListAST	p;
	ParaListAST() {
		v = null;
		p = null;
	}
	ParaListAST(VarDeclAST var,ParaListAST par){
		v=var;
		p=par;
		v.parent=p.parent=this;
	}
	void visit(Visitor v) {
		v.visitParaListAST(this);
	}
}
class EmptyParaListAST extends ParaListAST {
	EmptyParaListAST() {
		super();		
	}

	void visit(Visitor v) {
		v.visitEmptyParaListAST(this);
	}	
}

abstract class OneStmtAST extends AST{	
}

class CompStatAST extends OneStmtAST {
	VarDeclPartAST	v;
	StmtListAST	s;
	CompStatAST(VarDeclPartAST var, StmtListAST stmt){
		v=var;
		s=stmt;
		v.parent=s.parent=this;		
	}
	void visit(Visitor v) {
		v.visitCompStatAST(this);
	}	
}
class StmtListAST extends AST{
	OneStmtAST	o;
	StmtListAST	s;
	StmtListAST() {
		o = null;
		s = null;
	}
	StmtListAST(OneStmtAST one, StmtListAST stmt){
		o=one;
		s=stmt;
		s.parent=o.parent=this;		
	}
	void visit(Visitor v) {
		v.visitStmtListAST(this);
	}	
}
class EmptyStmtListAST extends StmtListAST {

	EmptyStmtListAST() {
		super();		
	}
	void visit(Visitor v) {
		v.visitEmptyStmtListAST(this);
	}
}
class AssiStmtAST extends OneStmtAST {
	LvalueAST	l;
	ExprAST		e;
	AssiStmtAST(LvalueAST lval, ExprAST exp){
		l = lval;
		e = exp;
		e.parent = this;
	}
	void visit(Visitor v) {
		v.visitAssiStmtAST(this);
	}	
}
class LvalueAST extends AST {
	Token name;
	ExprListAST e;
	LvalueAST(Token n,ExprListAST el) {
		name = n;
		e = el;
	}
	void visit(Visitor v) {
		v.visitLvalueAST(this);
	}
}
class CallStmtAST extends OneStmtAST {
	Token 		name;
	ExprListAST	e;
	CallStmtAST(Token t, ExprListAST exp){
		name=t;
		e=exp;
		e.parent=this;
	}
	void visit(Visitor v) {
		v.visitCallStmtAST(this);
	}	
}
class ForStmtAST extends OneStmtAST {
	Token		name;
	ExprAST		e1;
	ExprAST		e2;
	boolean		to; //true for TO and false for DOWNTO
	OneStmtAST	o;
	ForStmtAST(Token t, ExprAST exp1, ExprAST exp2, boolean bool,OneStmtAST one){
		name=t;
		e1=exp1;
		e2=exp2;
		to=bool; 
		o=one;
		e1.parent = e2.parent = o.parent = this;
	}
	void visit(Visitor v) {
		v.visitForStmtAST(this);
	}	
}
class IfThenStmtAST extends OneStmtAST {
	ExprAST		e;
	OneStmtAST	s1;
	IfThenStmtAST(ExprAST exp,OneStmtAST one){
		e=exp;
		s1=one;
		e.parent=s1.parent=this;		
	}
	void visit(Visitor v) {
		v.visitIfThenStmtAST(this);
	}	
}
class IfThenElseStmtAST extends OneStmtAST {
	ExprAST		e;
	OneStmtAST	s1;
	OneStmtAST	s2;
	IfThenElseStmtAST(ExprAST exp, OneStmtAST stmt1, OneStmtAST stmt2){
		e=exp;
		s1=stmt1;
		s2=stmt2;
		e.parent=s1.parent=s2.parent=this;
	}
	void visit(Visitor v) {
		v.visitIfThenElseStmtAST(this);
	}	
}
class RepeatStmtAST extends OneStmtAST {
	StmtListAST	s;
	ExprAST		e;
	RepeatStmtAST(StmtListAST stmt, ExprAST	exp){
		s=stmt;
		e=exp;
		s.parent=e.parent=this;
	}
	void visit(Visitor v) {
		v.visitRepeatStmtAST(this);
	}	
}
class WhileStmtAST extends OneStmtAST {
	ExprAST		e;
	OneStmtAST	o;
	WhileStmtAST(ExprAST exp, OneStmtAST stmt){
		e=exp;
		o=stmt;
		e.parent=o.parent=this;
	}
	void visit(Visitor v) {
		v.visitWhileStmtAST(this);
	}	
}
class BreakStmtAST extends OneStmtAST {
	void visit(Visitor v) {
		v.visitBreakStmtAST(this);
	}	
}
class ContStmtAST extends OneStmtAST {
	void visit(Visitor v) {
		v.visitContStmtAST(this);
	}	
}
class RetStmtAST extends OneStmtAST {
	ExprAST		e;
	RetStmtAST(ExprAST	exp){
		e=exp;
		e.parent=this;
	}
	void visit(Visitor v) {
		v.visitRetStmtAST(this);
	}	
}
class RetNullStmtAST extends OneStmtAST {
	void visit(Visitor v) {
		v.visitRetNullStmtAST(this);
	}	
}
abstract class ExprAST extends AST{
}
class BinExprAST extends ExprAST {
	ExprAST 	e1;
	Token		op;
	ExprAST		e2;
	BinExprAST(ExprAST exp1, Token t, ExprAST exp2){
		e1=exp1;
		op=t;
		e2=exp2;
		e1.parent=e2.parent=this;
	}
	void visit(Visitor v) {
		v.visitBinExprAST(this);
	}	
}
class UnaryExprAST extends ExprAST {
	Token		op;
	ExprAST		e;
	UnaryExprAST(Token t,ExprAST exp ){
		op=t;
		e=exp;
		e.parent=this;
	}
	void visit(Visitor v) {
		v.visitUnaryExprAST(this);
	}	
}
class VarExprAST extends ExprAST {
	Token		name;
	VarExprAST(Token t){
		name=t;		
	}
	void visit(Visitor v) {
		v.visitVarExprAST(this);
	}	
}

class EleExprAST extends ExprAST {
	Token		name;
	ExprAST		e;
	EleExprAST(Token t,ExprAST exp ){
		name=t;
		e=exp;
		e.parent=this;
	}
	void visit(Visitor v) {
		v.visitEleExprAST(this);
	}	
}
class CallExprAST extends ExprAST {
	Token 		name;
	ExprListAST	e;
	CallExprAST(Token t, ExprListAST exp){
		name=t;
		e=exp;
		e.parent=this;
	}
	void visit(Visitor v) {
		v.visitCallExprAST(this);
	}	
}
class ExprListAST extends AST {
	ExprAST		e;
	ExprListAST	l;
	ExprListAST() {
		e = null;
		l = null;
	}

	ExprListAST(ExprAST	exp,ExprListAST expl ){
		e=exp;
		l=expl;
		e.parent=l.parent=this;
	}
	void visit(Visitor v) {
		v.visitExprListAST(this);
	}	
}
class EmptyExprListAST extends ExprListAST {

	EmptyExprListAST() {
		super();		
	}
	void visit(Visitor v) {
		v.visitEmptyExprListAST(this);
	}
}


 
		
 